package com.yjd.comm.fs.util;

import com.yjd.comm.base.enums.DbWREnums;
import com.yjd.comm.enums.ReferenceTypeEnum;
import com.yjd.comm.fs.file.IFileService;
import com.yjd.comm.fs.file.IUpWrap;
import com.yjd.comm.fs.model.FileUploadedModel;
import com.yjd.comm.resource.model.ResourceModel;
import com.yjd.comm.resource.service.IResourceService;
import com.yjd.comm.util.*;
import com.yjd.comm.util.HttpsUtil.UploadFileModel;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文件上传和下载工具类
 * 
 * @author ready
 * 
 */
public class FileUtil {
	private static Logger logger = Logger.getLogger(FileUtil.class);

	private static String PICTURE_TYPE = ".+(.JPEG|.jpeg|.JPG|.jpg|.GIF|.gif|.BMP|.bmp|.PNG|.png)$";

	/**
	 * 获取文件服务
	 * 
	 * @return
	 */
	public static IFileService getFileService() {
		return SpringContextHolder.getBean("fileService");
	}

	/**
	 * 上传文件
	 * 
	 * @param uploadUrl
	 *            上传文件的路径
	 * @param inwrapList
	 *            上传文件的列表信息
	 * @return
	 * @throws Exception
	 */
	public static boolean upload(String uploadUrl, List<IUpWrap> inwrapList)
			throws Exception {
		boolean result = true;
		Map<String, UploadFileModel> requestInps = new LinkedHashMap<String, UploadFileModel>();
		Map<String, Object> requestParas = new LinkedHashMap<String, Object>();
		int i = 0;
		for (IUpWrap upWrap : inwrapList) {
			String fileFiledName = "file" + i++;
			requestInps.put(
					fileFiledName,
					new UploadFileModel(upWrap.getInputStream(), upWrap
							.getFileName()));
			requestParas.put(fileFiledName + "AbsPath",
					upWrap.getSaveAbsFilePath());
		}
		logger.debug(FrameUtil.json(requestParas));
		HttpsUtil.requestPostUploadByIs(uploadUrl, requestInps, requestParas);
		return result;
	}

	/**
	 * 下载文件
	 * 
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public static InputStream downLoadFile(String filePath) throws Exception {
		return HttpsUtil.requestGetResponse(filePath).getResponseStream();
	}

	/**
	 * 下载一个文件到指定的文件中
	 * 
	 * @param filePath
	 * @param file
	 * @throws Exception
	 */
	public static void downLoadFile(String filePath, File file)
			throws Exception {
		FileUtils.copyInputStreamToFile(downLoadFile(filePath), file);
	}

	/**
	 * 根据文件名称获取文件后缀
	 * 
	 * @param fileName
	 * @return
	 */
	public static String getFileStuffByFileName(String fileName) {
		if (StringUtil.isNotEmpty(fileName) && fileName.indexOf(".") != -1) {
			return fileName.substring(fileName.indexOf("."));
		}
		return "";
	}


	/**
	 * 将文件上传到远程，并记录到Resource表,(支持多个文件)
	 *
	 * @param uploadFiles 需要上传文件信息
	 * @param type 文件类型及远程存储路径
	 * @param res 本地资源信息
	 * @return 返回上传资源在远程的相对路径
	 * @throws
	 */
	public static String uploadFileToRemote(Map<String, MultipartFile> uploadFiles, ReferenceTypeEnum type, ResourceModel res) throws Exception{
		String remotefile = "";
		if(null == uploadFiles){
			return remotefile;
		}

		for(String key : uploadFiles.keySet()){
			remotefile = uploadFileToRemote(uploadFiles.get(key), type, res);
		}

		return remotefile;
	}

	/**
	 * 将文件上传到远程，并记录到Resource表,(单个文件)
	 *
	 * @param uploadFile 需要上传文件信息
	 * @param type 文件类型及远程存储路径
	 * @param res 本地资源信息
	 * @return 返回上传资源在远程的相对路径
	 * @throws
	 */
	public static String uploadFileToRemote(MultipartFile uploadFile, ReferenceTypeEnum type, ResourceModel res) throws Exception{
		String remotefile = "";
		if(null == uploadFile){
			return remotefile;
		}

		String originalName = uploadFile.getOriginalFilename();
		InputStream file = uploadFile.getInputStream();

		if(StringUtil.isEmpty(originalName) || null == file){
			// 需要上传的文件为空，可能是因为不需要图片
			return remotefile;
		}

		if(ReferenceTypeEnum.APP != type && ReferenceTypeEnum.MERCHANT_APP != type){
			Pattern pattern = Pattern.compile(PICTURE_TYPE);
			Matcher matcher = pattern.matcher(originalName.toLowerCase());
			if(!matcher.find()){
				FrameUtil.throwBaseException1("图片格式有误", null);
			}
			if(uploadFile.getSize()>5120*1024){
				FrameUtil.throwBaseException1("图片大小超过限制(5M)", null);
			}
		}

		String fileSuffix = originalName.substring(originalName.lastIndexOf("."));

		// 创建本地缓存文件
		File tempFile = new File(System.getProperty("java.io.tmpdir") + "/m_back_" + StringUtil.getRandomString(5) + fileSuffix);

		// 使用common io 工具将上传流中的图片数据写入本地缓存文件
		FileUtils.copyInputStreamToFile(file, tempFile);

		// 远程文件路径
		remotefile = generateRemoteFilePath(type, fileSuffix, res.getRef_id());

		// 将本地缓存文件上传到远程(OSS)
		FileUploadedModel fum  = OSSClientUtil.uploadFile2OSS(tempFile,remotefile);

		// 删除缓存文件
		tempFile.delete();

		// 记录本地信息
		Long currentTime = FrameUtil.getTime();
		res.setCreate_time(currentTime);
		res.setLast_update_time(currentTime);
		res.setPath(remotefile); // 本地只记录远程相对路径
		IResourceService resourceService = ServiceHolder.getLocalService(IResourceService.class, "resourceService");
		if(null != res.getRef_id()){
			ResourceModel dbRes = resourceService.getModelOne(
					FrameUtil.newHashMap("ref_type", type.getCode(), "ref_id", res.getRef_id()), DbWREnums.READ);
			// 如果已经有了，则先删除
			if(null != dbRes){
				resourceService.delete(dbRes.getId());
			}
		}

		resourceService.insert(res);

		return remotefile;
	}

	private static String generateRemoteFilePath(ReferenceTypeEnum type, String fileSuffix, Long ref_id){
		StringBuffer path = new StringBuffer();
		path.append(type.getPath());

		// 用户头像存储路径如：portrait/57.png
		if(type == ReferenceTypeEnum.PORTRAIT){
			path.append(ref_id);
			path.append(fileSuffix);
			return path.toString();
		}

		path.append(null == ref_id ? "detail/" : ref_id + "/");
		path.append(DateUtil.getDayString() + "/");
		path.append(StringUtil.getRandomString(8));
		path.append(fileSuffix);

		return path.toString();
	}

}
